package com.zhkeshe.keshe.Socket;

import com.alibaba.fastjson.JSONObject;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author daiyg
 * @date
 */
@Component
@ServerEndpoint(value = "/ws", subprotocols = {"protocol"})
public class WebSocketServer {


    private static int onlineCount = 0;
    private static ConcurrentHashMap<String, WebSocketServer> webSocketSet = new ConcurrentHashMap<>();
    private static  ConcurrentHashMap<String, List<String>> map = new ConcurrentHashMap<>();


    //与某个客户端的连接会话，需要通过它来给客户端发送数据
    private Session session;
    private static List<SidAndUUID> sidAndUUIDList=new ArrayList<>();
    private static Logger log = LogManager.getLogger(WebSocketServer.class);
    private String id = "";
    private String key= "";

    private static ApplicationContext applicationContext;

    public static boolean isOnline_ws(String deviceId){
        for (SidAndUUID e:sidAndUUIDList){
            if (e.getUUID().equals(deviceId)){
                return true;
            }
        }
        return false;
    }

    public static void setApplicationContext(ApplicationContext applicationContext) {
        WebSocketServer.applicationContext = applicationContext;
    }

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session) {
        sidAndUUIDList.add(new SidAndUUID(session.getId()));
        webSocketSet.putIfAbsent(session.getId(), this);
        this.session = session;
        //接收到发送消息的人员编号
        addOnlineCount();           //在线数加1
        log.info("用户" + id + "连接成功！当前在线人数为" + getOnlineCount());
        try {
            sendMessage("连接成功");
        } catch (IOException e) {
            log.error("websocket IO异常");
        }

    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        SidAndUUID.remove(sidAndUUIDList,this.session.getId());
        //删除map中值
        List<String> keys = map.get(this.id);
        for (int i = 0; i < keys.size(); i++) {
            if(this.key.equals(keys.get(i))){
                keys.remove(i);
                i--;
            }
        }
        webSocketSet.remove(this.key);  //从set中删除
        subOnlineCount();           //在线数减1
        log.info("有一连接关闭！当前在线人数为" + getOnlineCount());
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message) throws IOException {
        System.out.println(message);

        JSONObject jsonObject=JSONObject.parseObject(message);
        if(jsonObject.getString("MessageType").equals("Register")) {
            for (SidAndUUID e : sidAndUUIDList) {
                if (e.getSid().equals(this.session.getId())) {
                    //System.out.println(jsonObject.getJSONArray("Params").get(0).toString()+"ssssssss");
                    e.setUUID(jsonObject.getJSONArray("Params").get(0).toString());
                }
            }
            //sendMessage("welcome to mysystem");
        }
        else if(jsonObject.getString("MessageType").equals("心跳")) {
            for (SidAndUUID e : sidAndUUIDList) {
                if (e.getSid().equals(this.session.getId())) {
                    //System.out.println(jsonObject.getJSONArray("Params").get(0).toString()+"ssssssss");
                    e.setUUID(jsonObject.getJSONArray("Params").get(0).toString());
                    e.setIslive(true);//心跳设置
                }
            }
           // sendMessage("welcome to mysystem");
        }

    }

    /**
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("发生错误");
        try {
            session.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        error.printStackTrace();

    }

    /**
     * 服务端主动推送消息
     *
     * @param message
     * @throws IOException
     */
    public void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
    }

    /**
     * 发送信息给指定ID用户，如果用户不在线则返回不在线信息给自己
     *
     * @param message
     * @param personKeys
     * @throws IOException
     */
    public static void sendtoUser(String message, String[] personKeys) throws IOException {
        //获取人员集合
        for (String personKey : personKeys) {
            //获取map中对应的链接
            if (map.get(personKey) != null && map.get(personKey)!=null&&!map.get(personKey).equals("")) {
                //遍历给连接人发送信息
                for(String s : map.get(personKey)){
                    webSocketSet.get(s).sendMessage(message);
                }
            } else {
                //如果用户不在线则返回不在线信息给自己
                log.error("当前用户不在线：" + personKey);
            }
        }
    }

    public static void sendtoUUID(String uuid,String message) throws IOException {
        for (SidAndUUID e:sidAndUUIDList){
            if(e.getUUID().equals(uuid)){
                webSocketSet.get(e.getSid()).sendMessage(message);
            }
        }
    }



    /**
     * 发送信息给所有人
     *
     * @param
     * @throws IOException
     */
    public void sendtoAll(String message) throws IOException {
        for (String key : webSocketSet.keySet()) {
            try {
                webSocketSet.get(key).sendMessage(message);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    public static synchronized int getOnlineCount() {
        return onlineCount;
    }

    public static synchronized void addOnlineCount() {
        WebSocketServer.onlineCount++;
    }

    public static synchronized void subOnlineCount() {
        WebSocketServer.onlineCount--;
    }

}

